#ifndef _ABSTRACT_RDB_ACCESS_H_
#define _ABSTRACT_RDB_ACCESS_H_

#include <buildspec.h>
#include <Client/ClientUtils/Network/NetworkInterface.h>
#include <Client/ClientUtils/Network/RDBDriverInterface.h>
#include <Client/ClientUtils/Network/RDBAttribute.h>
#include <Geometry/SRSItem.h>
#include <Geometry/ClientGeometry.h>
#include <Geometry/IGeometry.h>

#include <ostream>
#include <utility>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>

namespace GST {

	//prototypes:
	namespace ClientGUI	{
		class ProgressControl;
	}

	//exception:
	namespace exceptions {	
		/**
		 * Thrown whenever a table or an attribute of a table in GST schema can not found.
		 */
		class GSTDatamodelCorruption
			: public GSTRuntimeException
		{
		public:
			GSTDatamodelCorruption(const std::string & throwLocation, const std::string& message)
				: GSTRuntimeException(throwLocation,"")
			{
				this->_msg = "Model corruption! Message: " + message;
			}
			GSTDatamodelCorruption(const std::string & throwLocation, const SQLSyntaxError& queryError)
				: GSTRuntimeException(throwLocation,"")
			{
				this->_msg = "Model corruption! Message: " + queryError.getMessage() + ". The following query failed: "+queryError.getQuery();
			}
		};

		class RequestFormatUnkown
			: public GSTRuntimeException
		{
		public:
			RequestFormatUnkown(const std::string & throwLocation, const Geometry::IGeometry::RequestFormat & format)
				: GSTRuntimeException(throwLocation,"")
			{
				this->_msg = "Format type \""+boost::lexical_cast<std::string>(format)+"\" not registered.";
			}
		};

		class ServerProcedureStoppedConnection
			: public ConnectionTerminated
		{
		public:
			std::string executingMethod;

			ServerProcedureStoppedConnection(const std::string & throwLocation, const std::string & executingMethod, const ConnectionTerminated & e)
				: ConnectionTerminated(throwLocation, e.getMessage(), e.host, e.dbname, e.query)
				, executingMethod(executingMethod)
			{
				this->_msg += " Execution of procedure \""+executingMethod+"\" failed.";
			}
			virtual ~ServerProcedureStoppedConnection() throw()
			{}
		};

		class CreatePropertyTableException
			: public GSTRuntimeException
		{
		public:
			ClientUtils::FeatureClassDesc featureClass;

			CreatePropertyTableException(const std::string & throwLocation, const std::string & msg, const ClientUtils::FeatureClassDesc & fclass)
				: GSTRuntimeException(throwLocation,msg)
				, featureClass(fclass)
			{
			}
			virtual ~CreatePropertyTableException() throw()
			{
			}
		};

		class BadFromStringTypeCast
			: public GSTRuntimeException
		{
		public:
			std::string badtypestring;

			BadFromStringTypeCast(const std::string & throwLocation, const std::string & msg, const std::string& typeString)
				: GSTRuntimeException(throwLocation,msg)
				, badtypestring(typeString)
			{
			}
			virtual ~BadFromStringTypeCast() throw()
			{
			}
		};

		class GeometryTypeCast
			: public BadFromStringTypeCast
		{
		public:
			GeometryTypeCast(const std::string & throwLocation, const std::string & msg, const std::string& geometryTypeString)
				: BadFromStringTypeCast(throwLocation,msg,geometryTypeString)
			{ 
			}
		};

		class LockTypeCast
			: public BadFromStringTypeCast
		{
		public:
			LockTypeCast(const std::string & throwLocation, const std::string & msg, const std::string& lockTypeString)
				: BadFromStringTypeCast(throwLocation,msg,lockTypeString)
			{ 
			}
		};

		class InsertingColorMapSegmentFailed
			: public GSTRuntimeException
		{
		public:
			InsertingColorMapSegmentFailed(const std::string & throwLocation, const std::string & msg)
				: GSTRuntimeException(throwLocation,msg)
			{ 
			}
		};
	}

namespace ClientUtils {
	/**
	 * Configuration for the database. Inherit from here to make 
	 * db type specific configuration.
	 *
	 * @todo may merge in future releases with Host and DB name/service name
	 */
	struct GST_API_EXPORT RDBConfig
		: public DBConfig
	{
		std::string functionSchema;
		std::string baseSchema;

		virtual bool doCompare(const DBConfig& other) const;

		virtual ~RDBConfig() {}
	};
	typedef boost::shared_ptr<RDBConfig> RDBConfigPtr;

	/**
	 * Base class for stored procedures parameters
	 */
	struct GST_API_EXPORT SPParameter
	{
		/**
		 * defines the data type of the sproc parameter
		 */
		enum DType
		{
			SPPINT, /*!< 32bit integer  */
			SPPLONG, /*!< 64bit integer (maybe) */
			SPPFLOAT, /*!< 4 byte floating point */
			SPPDOUBLE, /*!< 8 byte floating point */
			SPPSTR, /*!< varchar equivalent (up to 4000 characters) */
			SPPTXT, /*!< big text type (1GB PG, 4GB ORA, 2GB MSSQL) */
			SPPBIN /*!< raw binary type (1GB PG, 4GB ORA, 2GB MSSQL) */
		};
		std::string name;
		DType datatype;

		SPParameter(std::string name, DType datatype)
			: name(name)
			, datatype(datatype)
		{}

		virtual SPParameter * clone() const = 0;									
	};

	SPParameter * new_clone( const SPParameter & other );

	/**
	 * Stored procedures input parameters
	 */
	struct GST_API_EXPORT SPInParameter
		: public SPParameter
	{
		boost::any value;

		SPInParameter(std::string name, boost::any value, DType datatype)
			: SPParameter(name, datatype)
			, value(value)
		{}

		virtual SPParameter * clone() const
		{
			return new SPInParameter(this->name, this->value, this->datatype);
		}
	};

	/**
	 * Stored procedures output parameters
	 */
	struct GST_API_EXPORT SPOutParameter
		: public SPParameter
	{  
		void * outputBind;

		SPOutParameter(std::string name, DType datatype, void * outputBind)
			: SPParameter(name, datatype)
			, outputBind(outputBind)
		{}

		virtual SPParameter * clone() const
		{
			return new SPOutParameter(this->name, this->datatype, this->outputBind);
		}
	};

	/**
	 * Stored procedure description
	 */
	struct GST_API_EXPORT SPDesc
	{
		std::string spName;
		std::string spNamespace;
		boost::ptr_vector<SPParameter> spParameters;

		bool adminFunction;
		bool inDefaultNameSpace;
		/**
		 * Tells if context is necessary
		 *
		 * @note currently only used in MSSQLAccess
		 */
		bool needContext;

		SPDesc()
			: adminFunction(false)
			, inDefaultNameSpace(true)
			, needContext(true)
		{}

		virtual ~SPDesc()
		{}
	};
	typedef boost::shared_ptr<SPDesc> SPDescPtr;

//------------------------------------------------------------------------------

	/**
	* Base class for prepared statement parameters
	*/
	struct GST_API_EXPORT PSParameter
	{
		enum DType { 
			PSSTR, PSINT, PSLONG, PSFLOAT, PSDOUBLE, PSSERIAL, PSBOOL 
		};
		std::string name;
		DType datatype;
		bool quote;
		bool nullValue;

		PSParameter(std::string name, DType datatype)
			: name(name)
			, datatype(datatype)
			, quote(true)
			, nullValue(false)
		{}

		bool IsCompatible(TableAttributeDesc::DType tableDataType) const
		{
			switch (datatype)
			{
			case GST::ClientUtils::PSParameter::PSSTR:
				return tableDataType == TableAttributeDesc::TypeText;
				break;
			case GST::ClientUtils::PSParameter::PSINT:
				return tableDataType == TableAttributeDesc::TypeInt;
				break;
			case GST::ClientUtils::PSParameter::PSSERIAL:
			case GST::ClientUtils::PSParameter::PSLONG:
				return 
					tableDataType == TableAttributeDesc::TypeSerial
					|| tableDataType == TableAttributeDesc::TypeLong;
				break;
			case GST::ClientUtils::PSParameter::PSFLOAT:
				return tableDataType == TableAttributeDesc::TypeFloat;
				break;
			case GST::ClientUtils::PSParameter::PSDOUBLE:
				return tableDataType == TableAttributeDesc::TypeDouble;
				break;
			case GST::ClientUtils::PSParameter::PSBOOL:
				return tableDataType == TableAttributeDesc::TypeBool;
				break;
			default:
				return false;
				break;
			}
		}

		bool isNull() const
		{
			return nullValue;
		}
	};

	/**
	* prepared statement input parameters
	*/
	struct GST_API_EXPORT PSInParameter
		: public PSParameter
	{
		boost::any value;

		PSInParameter(std::string name, boost::any value, DType datatype)
			: PSParameter(name, datatype)
			, value(value)
		{}
	};
	typedef boost::shared_ptr<PSInParameter>  PSInParameterPtr;
	typedef std::vector<PSInParameterPtr> PSInParameterList;

	/**
	* prepared statement output parameters
	*/
	struct GST_API_EXPORT PSOutParameter
		: public PSParameter
	{
		void * outputBind;

		PSOutParameter(std::string name, DType datatype, void * outputBind)
			: PSParameter(name, datatype)
			, outputBind(outputBind)
		{}
	};
	typedef boost::shared_ptr<PSOutParameter> PSOutParameterPtr;
	typedef std::vector<PSOutParameterPtr> PSOutParameterList;

	/**
	  * abstract base class
	  */	
	struct GST_API_EXPORT PreparedStatementDesc
	{
		PSInParameterList  inputParameters;
		PSOutParameterList outputParameters;

		virtual ~PreparedStatementDesc()
		{}

		///deep copy clone
		PSInParameterList inputParametersClone() const;
		PSInParameterPtr InputParameterByName(const std::string & name);
	};
	typedef boost::shared_ptr<PreparedStatementDesc> PreparedStatementDescPtr;

	/**
	  * Inserts into tableName the inputParameters and if there are any
	  * outputParameters the values returned into PSOutParameter::outputBind
	  */
	struct GST_API_EXPORT InsertStatementDesc
		: public PreparedStatementDesc
	{
		std::string tableName;
		bool quoteTableName;

		InsertStatementDesc(const std::string & tableName, bool quoteTableName = true)
			: tableName(tableName)
			, quoteTableName(true)
		{}

		virtual ~InsertStatementDesc()
		{}
	};
	typedef boost::shared_ptr<InsertStatementDesc> InsertStatementDescPtr;

	/**
	  * Updates table tableName by the value provided by 
	  * PreparedStatementDesc::inputParameters. The update will be performed
	  * on row that are satisfied by condition (=SQL: "... WHERE <condition>")
	  */
	struct GST_API_EXPORT UpdateStatementDesc
		: public PreparedStatementDesc
	{
		std::string tableName;
		bool quoteTableName;
		std::string condition;

		UpdateStatementDesc(const std::string & tableName, bool quoteTableName = true);
		UpdateStatementDesc(const InsertStatementDesc & insert, const std::string & condition);

		virtual ~UpdateStatementDesc()
		{}
	};
	typedef boost::shared_ptr<UpdateStatementDesc> UpdateStatementDescPtr;
	
	//-------------------------- class of headerfile --------------------------------

	using GST::Geometry::IGeometry;

	struct IntersectionImageParameter;
	struct IntersectionResult;

	/**
	 * Abstract base class handle NetworkInterface functions and implement those to direct connected
	 * Relational Database backend. Its derived classes need overload functions which
	 * using SQL slang or DB specific behavior like getCurrentUser().
	 */
	class GST_API_EXPORT AbstractRDBAccess
		: public NetworkInterface
	{
	public:
		AbstractRDBAccess( RDBConfigPtr dbconfig );
		virtual ~AbstractRDBAccess();
		
		///@name AbstractRDBAccess interface
		//@{
		virtual RDBDriverInterface * getRDBDriver() const = 0;
		/**
		  * Runs an INSERT RETURNING statement.
		  *
		  * PreparedStatementDesc::inputParameters describing the insert columns
		  * and the values that are inserted. PreparedStatementDesc::outputParameters
		  * are used for the RETURNING clause. The returned values are written to
		  * PSOutParameter::outBind varaible pointing to a valid adress of the 
		  * adequate data type (bool, int, std::string, etc.)
		  *
		  * If no outputParameters are given
		  * (outputParameters.size() == 0 ) the prpepared statment that is 
		  * executed is simply inserting.
		  */
		virtual void RunPreparedInsertStatement(const InsertStatementDesc & preparedStatement) = 0;
		virtual void RunPreparedUpdateStatement(const UpdateStatementDesc & preparedStatement) = 0;
		//@}

		///@name NetworkInterface members
		//@{
		virtual void connect();
		virtual void disconnect();
		virtual bool isConnected() const;
		virtual bool isSSLUsed() const;
		virtual std::string GetStorageRevision() const;
		virtual std::string getEndPointName() const;
		virtual std::string getUserName() const;
		virtual EndPointPtr getEndPoint() const;
		virtual int CheckStorageLicense(const std::string &license,
								 const std::string &version,
								 std::string * errorMessage = NULL);
		virtual AccessLevelListPtr ListAccessLevels() const;
		virtual AccessLevelPtr GetAccessLevelById(long accessLevelId) const;
		virtual ServiceDescriptionPtr CreateService(const std::string &name, const std::string &url, long accessLevelId, const std::string &user, const std::string &secret) const = 0;
		virtual ServiceDescriptionPtr UpdateService(long serviceId, const std::string &name, const std::string &url, long accessLevelId, const std::string &user, const std::string &secret) const = 0;
		virtual ServiceDescriptionPtr GetServiceDescriptionById(long serviceId) const ;
		virtual void DropService(long serviceId) const;
		virtual ServiceDescrionListPtr ListServices() const;
		virtual ServiceDescrionListPtr ListServicesByAccessLevel(long accessLevelId) const;
		virtual ServerInfoPtr GetServerInformation();
		virtual DataTablePtr GetServerInformationTable() const;
		virtual bool TableIsSelectable(const std::string & fullTableName) const;
		virtual bool ColumnExistInTable(const std::string & fullTableName, const std::string & columnName) const;
		virtual NamesListPtr ListAllTables() const =0;
		virtual bool ViewRefersTable(const std::string& tablename, const std::string& viewname) const =0;
		virtual NamesListPtr ListAllViewsRefersTable(const std::string& tablename) const =0;  
		virtual NamesListPtr ListAllColumns(const std::string& tablename) const =0;
		virtual NamesListPtr ListPrimaryKeyColumns(const std::string& tablename) const =0;
		virtual std::string GetExactColumnDataType(const std::string& columnname) const=0;
		virtual ClientUtils::TableAttributeDesc::DType GetColumnDType(const std::string& columnname) const =0;
		virtual ConstrainedTableAttributeValArrayPtr GetConstrainedPropertyValues(const TableAttributeDesc& cp) ;  		
		virtual FeatureClassDescListPtr ListFeatureClasses();
		virtual void InstantUpdateFeature( const Geometry::StreamableGeometry & feature, const long & idgeo, const FeatureClassDesc & target, long commitKey = -1, bool updateStats = true );
		virtual int CountFeatures(const FeatureClassDesc& featureClass) const;
		virtual CrudeFeaturePtr GetFeature(
			const FeatureDesc &feature,
			const Geometry::IGeometry::RequestFormat &geometryformat,
			Geometry::SRSPtr srs,
			const boost::optional<AreaLimiter> &areaLimiter,
			bool lock = false,
			long commitKey = -1);
		virtual void MoveFeature(const FeatureDesc& feature, const FeatureClassDesc& target, const std::string& targetfeaturename = "");
		virtual void DeleteFeature(long id) const;
		virtual void DeleteFeatureClass( const std::string & featureClassName );
		virtual FeatureClassDescPtr RenameFeatureClass( FeatureClassDetailedDesc& featureClassDesc, const std::string& newName );
		virtual FeatureClassDescPtr ChownFeatureClass(
			const FeatureClassDesc &featureClassDesc,
			const Owner &newOwner,
			const std::string &newName = std::string()) const;
		virtual FeatureClassDescPtr CreateFeatureClassSnapshot(
			const FeatureClassDesc &sourceFeatureClass,
			const Owner &owner,
			const std::string &name,
			const std::string &commitMessage) const;
		virtual std::pair<FeatureClassDescPtr, FeatureDescListPtr>
		CreateFeatureSelectionSnapshot(
			const FeatureDescListPtr &features,
			const Owner &owner,
			const std::string &name,
			const std::string &commitMessage,
			const boost::optional<AreaLimiter> &areaLimiter
			= boost::none) const;
		virtual AssignableFeatureDescListPtr ListAllFeatures(const FeatureClassDesc& featureClass) const;
		virtual TableConstrainedAttributeDescPtr UpdateConstrainedPropertyDesc(const TableConstrainedAttributeDesc & cp) const;
		virtual GeoColumnDescPtr GetGeoColumnDesc(const FeatureClassDesc& featureClass) const;
		virtual FeatureDescPtr GetFeatureDescByGeomId( const long & idgeo ) const;
		virtual FeatureDescPtr GetFeatureDescByLockId( const std::string & lockid ) const;
		virtual SimplexPropertyDescListPtr GetSimplexPropertyList( const FeatureClassDesc& featureClass ) const;
		virtual ObjectPropertyDescListPtr GetObjectPropertyList( 
			const FeatureClassDesc& featureClass
			, bool filterMemberProperties = true) const;
		virtual TableAttributeValListPtr GetObjectPropertyValues( const FeatureDesc & feature, const TableAttributeDescList& selection=TableAttributeDescList()) const;
		virtual	boost::any GetValueOfConstrainedObjectProperty(GST::ClientUtils::ConstrainedTableAttributeValPtr cop_val) const;
		virtual	void CreateTable( const GST::ClientUtils::TableAttributeDescList & attributes
			, bool quoteTablename = true );
		virtual void DropTable( const std::string & tableName
			, bool quoteTablename = true );
		virtual void InsertRecord( const GST::ClientUtils::TableAttributeValList & attributes, bool quoteTablename = true);
		virtual void DeleteRecord(
			const GST::ClientUtils::TableAttributeVal &attribute,
			bool quoteTablename = true) const override;
		virtual DataTablePtr GetTableValues( const std::string & tablename, const TableAttributeDescList & selection = TableAttributeDescList(), const std::string & filter = std::string() ) const;
		virtual void UpdateTableValues( RecordPtr record );
		virtual void UpdateObjectPropertyValue( const FeatureDesc & feature, const TableAttributeVal& value );
		virtual void UpdateObjectPropertyValue( const FeatureDesc & feature, const ConstrainedTableAttributeVal& value );
		virtual void AppendObjectProperty( const FeatureClassDesc& featureClass, const TableAttributeDesc& attribute );
		virtual void AppendSimplexProperty( const FeatureClassDesc& featureClass, const TableAttributeDesc& attribute );
		virtual void AppendConstrainedObjectProperty(const FeatureClassDesc& featureClass, const ConstrainedObjectPropertyDesc& attribute);
		virtual void AppendConstrainedSimplexProperty(const FeatureClassDesc& featureClass, const ConstrainedSimplexPropertyDesc& attribute);
		virtual ConstrainedObjectPropertyDescPtr GetConstrainedObjectProperty(const FeatureClassDesc& featureClass, const std::string propertyName) const;
		virtual ConstrainedSimplexPropertyDescPtr GetConstrainedSimplexProperty(const FeatureClassDesc& featureClass, const std::string propertyName) const;
		virtual void RenameProperty( const FeatureClassDesc& featureClass, TableAttributeDescPtr attribute, const std::string& newName ) const;
		virtual void DeleteProperty(const FeatureClassDesc& featureClass, const std::string propertyName, bool isObjectProp = true);
		virtual ObjectPropertiesByIdgeoMapPtr GetObjectPropertyValuesOfFeatureClass(const FeatureClassDesc&, const TableAttributeDescList&) const;
		virtual void DeleteConstrainedProperty(const FeatureClassDesc& featureClass, const std::string propertyName, const bool isObjectProp = true);
		virtual NamesListPtr ListConstrainedProperties(const FeatureClassDesc& featureClass, bool IsObject) const;
		virtual LockInfoListPtr GetLockInfo( long idgeo )  const;
		virtual std::string LockGeometry(long idgeo);
		virtual AbstractRDBAccess * RDBAccess();
		virtual GSTbox GetFeatureBboxTransformed(
				const FeatureDesc &fDesc,
				Geometry::SRSPtr targetSrs) const;
		virtual std::string MakeValidTableName( 
			const std::string tableNameStump, const std::string & suffix = std::string(""), 
			bool quote_tableName = true, int randomChars = 3 ) const;
        virtual std::string compute_histogram( const long& idgeo, const std::string& property, const std::string& ranges) const;
		virtual boost::shared_ptr<std::string> GetSimplexPropertiesAsCsv(const FeatureDesc & feature, long commitKey = -1) const;
        virtual std::string getSimplexPropertyValueAtXYZ(const long& idgeo, const double& x, const double& y, const double& z, const std::string& property) const;
        virtual std::vector<unsigned char> GetColorsFromIdx(const long& idgeo, const std::string& property, const std::string& vrtxIdxList, const ColorMap::Id &colorMapId) const;
		virtual void WriteGridSlices(long idgeo,
									 const std::string &propertyName,
									 long colorMapId,
									 Geometry::SRSPtr srs,
									 const std::string &outputPath) const;

		///@name user handling
		//@{
		virtual void CreateUser(const User& user, const std::string & initialgroupName);
		virtual void DropUser(const std::string & name);
		virtual void CreateGroup(const Group& group);
		virtual void DropGroup(const std::string & name);			
		virtual void AddUserToGroup(const std::string& userName, const std::string& groupName);
		virtual void DropUserFromGroup(const std::string& userName, const std::string& groupName);		 
		virtual UserListPtr GetAllGSTUsers() const;
		virtual GroupListPtr GetAllGSTGroups() const;
		virtual void ChangeUserPasswordAsAdmin(
			const User &user,
			const std::string &newPassword) const override;
		//@}
		
        ///@name web user handling)
		virtual dbLogin loginWebUser(const webLogin&) const;
        virtual void createWebUser(const webLogin&, const long&, const char&, const char&) const;
        virtual void updateWebUser(const std::string &oldName, const std::string &newName, const std::string &newPassword, long newAccessLevel, char newAllowUpload, const char newAllowSHPSection) const;
		virtual void dropWebUser(const std::string&) const;
		virtual void mapWebToDbUser(const webLogin&, const dbLogin) const;
		virtual void removeWebFromDbUser(const webLogin&, const dbLogin) const;
		virtual WebuserDescListPtr listWebUsers() const;
		virtual webToDbMappingList listWebToDbUserMapping() const;
		
		//@}

		///@name SRS Handling
		//@{
		virtual Geometry::GSTSRSRefPtr InsertSRS(const Geometry::SRS & new_srs, const std::string & label, const std::string & code_type = std::string(), const std::string & code_value = std::string() );
		virtual void UpdateSRS(const Geometry::SRSItemVal & new_srs);
		virtual void SetSRSForFeatureClass(const Geometry::GSTSRSRef & new_srs, const FeatureClassDesc & fclass);
		virtual void UnsetSRSForFeatureClass(const FeatureClassDesc & fclass);
		virtual void ChangeSRSForFeatureClass(const Geometry::GSTSRSRef & new_srs, const FeatureClassDesc & fclass);
		virtual void DeleteSRS(const Geometry::GSTSRSRef & srsref);
		virtual Geometry::SRSItemDescListPtr ListAllSRS() const;
		virtual Geometry::SRSItemDescPtr GetSRSDetailByKey(long srsKey) const;
		virtual Geometry::SRSItemValPtr GetSRSDefinition(long srsKey) const;
		virtual std::string GetProj4ParamFromSRS(const Geometry::SRS &srs) const;
		//@}
		//@}

		///@name Model Management
		//@{
		virtual LevelListPtr GetLevels() const;
		virtual LinkAdjacencyListPtr GetChilds(LinkAdjacency::LinkId parent) const;
		virtual LinkAdjacencyListPtr GetAllLinkAdjacencies() const;
		virtual LinkAdjacencyListPtr GetAllElementLinkAdjacencies() const;
		virtual LinkAdjacencyListPtr GetAllFeatureLinkAdjacencies() const;
		virtual LinkAdjacencyListPtr GetParentsForFeature(LinkAdjacency::LinkId featureId) const;
		virtual AssignableElementListPtr GetElements(Owner::OwnerId owner, Level::LevelDepth levelId) const;
		virtual ElementListPtr GetAllElements() const;
		virtual void RenameElement(ElementPtr Element, bool uniqueName = false) const;
		virtual ElementPtr ChownElement(const Element &element,
										const Owner &newOwner,
										const std::string &newName
										= std::string()) const override;
		virtual OwnerListPtr GetOwners() const;
		virtual OwnerListPtr GetAllOwners() const;
		virtual void UpdateLinkAdjacencySiblingRank(LinkAdjacency::LinkId linkId, int64_t newSiblingRank) const;
		virtual void DropLinkAdjacency(LinkAdjacency::LinkId linkId) const;
		virtual void DropElement(Element::ElementId id) const;
		//virtual void CreateLevel(LevelPtr level) const;
		//virtual void DropLevel(Level::LevelDepth depth) const;
		virtual ColorScaleListPtr GetColorScales() const;
		virtual ColorValueListPtr GetColorValues( ColorScale::ColorScaleId colorscale ) const;
		virtual ColorValuePtr GetColorValue(LinkAdjacency::LinkId lId, ColorScale::ColorScaleId cId) const;
		virtual void DeleteColorScale(ColorScale::ColorScaleId csId) const;
		virtual void DeleteColorValue(ColorValue::ColorValueId cvId) const;
		virtual void AssignColorScale(ColorScale::ColorScaleId csID, Element::ElementId eId) const;
		virtual void AssignColorValue(ColorValue::ColorValueId cvId, LinkAdjacency::LinkId lId) const;
		virtual void UnAssignColorScale(ColorScale::ColorScaleId csID, Element::ElementId eId) const;
		virtual void UnAssignColorValue(ColorValue::ColorValueId cvId, LinkAdjacency::LinkId lId) const;
		virtual long GetGeomIdFromLinkId(LinkAdjacency::LinkId linkid) const;
		virtual FeatureClassDescPtr ResolveFeatureClassFromGeometryId( const long & geometryId ) const;
		virtual void ForceUnlinkGeometry( long geometryId );
		//@}

		///@name Dynamic Color Values
		//@{
		virtual void CreateUpdateDynamicColorScale(DynamicColorScalePtr dyncs);
		virtual void DropDynamicColorScale(const DynamicColorScale::ID & dyncs_id);
		virtual DynamicColorScaleListPtr ListDynamicColorScales() const;
		virtual DynamicColorScalePtr GetDynamicColorScale(const DynamicColorScale::ID & dyncs_id) const;
		//@}

		///@name Slices/Sections
		//@{
		virtual IntersectionInfoPtr SaveBoreholeImage(const BoreHoleImageParameters &boreholeParams, const OutputImageParameters &outputImageParams) const;

		virtual IntersectionInfoPtr SaveSectionImage(const SectionImageParameters &sectionParams, const OutputImageParameters &outputImageParams) const;

		virtual IntersectionInfoPtr SaveMapImage(const MapImageParameters &mapParams, const OutputImageParameters &outputImageParams) const;

		virtual std::string SaveBoreholeAsShapefileZip(const BoreHoleImageParameters &boreholeParams, const OutputShapeParameters &outputShapeParams) const;
		virtual std::string SaveSectionAsShapefileZip(const SectionImageParameters &sectionParams, const OutputShapeParameters &outputShapeParams) const;
		virtual std::string SaveMapAsShapefileZip(const MapImageParameters &mapParams, const OutputShapeParameters &outputShapeParams) const;

		virtual IntersectionInfoPtr SaveBoreholeGridImage(const BoreholeGridImageParameters &boreholeParams, const OutputImageParameters &outputImageParams) const;
		virtual IntersectionInfoPtr SaveSectionGridImage(const SectionGridImageParameters &sectionParams, const OutputImageParameters &outputImageParams) const;
		virtual IntersectionInfoPtr SaveMapGridImage(const MapGridImageParameters &mapParams, const OutputImageParameters &outputImageParams) const;

		virtual ColorMap::Id CreateColorMap(
			const std::string &name,
			const ColorMapSegmentList &segments,
			const Geometry::IGeometry::Color &nodataColor,
			const std::string &regex,
			long accessLevelId,
			bool nodataTransparentForGrids = false);
		virtual ColorMap::Id CreateDiscreteColorMap(
			const std::string &name,
			const ColorMapDiscreteValueList &values,
			const Geometry::IGeometry::Color &nodataColor,
			const std::string &regex,
			long accessLevelId,
			bool nodataTransparentForGrids = false);
		virtual void UpdateColorMap(
			const ColorMap::Id &id,
			const std::string &name,
			const ColorMapSegmentList &segments,
			const Geometry::IGeometry::Color &nodataColor,
			const std::string &regex,
			long accessLevelId,
			bool nodataTransparentForGrids = false);
		virtual void UpdateDiscreteColorMap(
			const ColorMap::Id &id,
			const std::string &name,
			const ColorMapDiscreteValueList &values,
			const Geometry::IGeometry::Color &nodataColor,
			const std::string &regex,
			long accessLevelId,
			bool nodataTransparentForGrids = false);
		virtual void DeleteColorMap( const ColorMap::Id & id );
		virtual ColorMapDescListPtr ListColorMaps() const;
		virtual ColorMapPtr GetColorMap( const ColorMap::Id & id ) const;

		virtual void CreateRtreeIndex(long idgeo) const;
		virtual bool HasRtreeIndex(long idgeo) const;
		virtual void DropRtreeIndex(long idgeo) const;
		//@}
		
		///Versioning
		//@{
		virtual CommitListPtr ListCommits() const;
		virtual CommitListPtr ListCommitsByFeature( long geometryId );
		virtual CommitVersionListPtr ShowCommit( Commit::CommitKey key ) const;
		//@}

		///@name LOD Handling
		//@{
		virtual AssignableFeatureDescListPtr GetLODs(const FeatureDesc & feature) const;
		virtual void AddLOD(const FeatureDesc & parentLevel, const FeatureDesc & fineLevel);
		virtual void RemoveLOD(const FeatureDesc & parentLevel, const FeatureDesc & fineLevel);
		//@}

		///@name candidates for NetworkInterface
		//@{
		std::string getPropertyTableName( const FeatureClassDesc& featureClass ) const;
		std::string FunctionSchema() const;
		std::string BaseSchema() const;
		int GetProscatalogID(const std::string & tablename) const;
		long GetProscatalogIDForProstable(const std::string & tablename) const;
		//@}

		///@name local helpers
		//@{
		std::string quote_ident(const std::string & identifer) const;
		std::string quote_literal(const std::string & literal) const;
		//@}

		virtual int CheckStorageModuleLicense(const Module &module,
									   std::string *errorMessage = NULL,
									   const std::string &version = "2.0");

		virtual void updateSchemaStats() const = 0;

		virtual PropertyAliasPtr GetObjectPropertyAlias(const ObjectPropertyDesc &opDesc) const;
		virtual PropertyAliasPtr GetSimplexPropertyAlias(const SimplexPropertyDesc &spDesc) const;
		virtual void CreateUpdateObjectPropertyAlias(const ObjectPropertyDesc &opDesc, const PropertyAlias &propertyAlias) const;
		virtual void CreateUpdateSimplexPropertyAlias(const SimplexPropertyDesc &spDesc, const PropertyAlias &propertyAlias) const;
		virtual void DropObjectPropertyAlias(const ObjectPropertyDesc &opDesc) const;
		virtual void DropSimplexPropertyAlias(const SimplexPropertyDesc &spDesc) const;
		virtual PropertyAliasMapPtr GetObjectPropertyAliasList(const FeatureClassDesc& featureClass) const;
		virtual PropertyAliasMapPtr GetSimplexPropertyAliasList(const FeatureClassDesc& featureClass) const;

		virtual std::string getLatestGeoJSONHullGeometry(
			const long &idgeo) const;
		virtual void deleteLatestGeometryHull(const long &idgeo) const;
		virtual long calculateConcaveHull(const long &idgeo) const;
		virtual long uploadLatestHullForGeometry(
			const std::string &file_path,
			const std::string &file_name,
			const Geometry::IFileSerialisable::FileType &file_type,
			const long &idgeo) const;
		virtual bool hasGeometryHull(const long &idgeo) const;

#ifdef WITH_GST_TESTS
	virtual void test_sproc(const Params &in, Params &out) const;

#endif //WITH_GST_TESTS

	protected:

		///The driver for specific database
		RDBInterfacePtr dbconnection;
		///@name SQL generation helper
		//@{
		virtual std::string GenSQLDeleteColumn(ForeignKeyPtr fk) = 0;
		virtual std::string GenSQLEndTransaction(const std::string& errormessage="") =0;
		virtual std::string GenSQLBeginTransaction() = 0;
		virtual std::string GenSQLAddColumn( const std::string & table, const TableAttributeDesc& attribute ) = 0;
		void GenSQLKeyValue( const std::string & key, const boost::any & value, TableAttributeDesc::DType dtype, std::string &keyValue_OUT);
		void GenSQLValue( const boost::any & value, TableAttributeDesc::DType dtype, std::string &value_OUT);
		virtual void GenSQLForeignKeyConstraint(ForeignKeyPtr kc, const std::string& cpname, std::string& sql_OUT) = 0;
		virtual std::string GenSQLValueList( const TableAttributeValList & attributes, const std::string & glue=std::string(",") );
		//@}

		///@name virtual helpers
		//@{
		virtual RDBAttributeDescListPtr toRDBAttributeList( const TableAttributeDescList& list ) const;
		virtual AbstractRDBAttributeDescPtr toRDBAttribute( const TableAttributeDesc& attribute ) const;
		virtual AbstractRDBAttributeValPtr toRDBAttribute( const TableAttributeVal& attribute ) const;

		virtual AbstractRDBAttributeVal * newAttributeVal(const TableAttributeVal & val) const = 0;
		virtual AbstractRDBAttributeDesc * newAttributeDesc(const TableAttributeDesc & desc, bool is_primaryKey=false) const = 0;
		virtual void RunSP(SPDescPtr storedProcedure) const = 0;
		virtual GST::Protocol GetProtocol() const = 0;

		virtual void RenameFeatureClass_Impl( const FeatureClassDesc& featureClassDesc, const std::string& newName ) = 0;
		virtual void CheckIfElementNameIsUnique_impl(const std::string &name, std::string& sqlstatement) const;
		virtual std::string ReportInputParameterValues(const PSInParameterList & psInputVars) const;
		virtual void AppendConstrainedProperty_impl(const FeatureClassDesc& featureClass, const std::string& propertyName, const TableConstrainedAttributeDesc& attribute, const bool isObjectProperty);

		//@}

		///@name type interpreted (type outputs may be db depended so)
		//@{
		virtual IGeometry::GeometryType GeomTypeStr2GeomTypeEnum( const std::string & typestring ) const;
		virtual LockState::LockType LockTypeStr2LockTypeEnum( const std::string & typestring ) const;
		//virtual TableAttributeDesc::DType DatatypeStr2TableAttributeDescDType( const std::string & typestring ) const = 0;
		//@}

		///@name helpers
		//@{
		void testInterfacePtr() const;
		void ExtractGroupAndClassFromFeatureClassName( const std::string & featureClassName, std::string & groupName, std::string & className, bool & is_private );

		virtual void RenameProperty_Impl( const FeatureClassDesc& featureClass, TableAttributeDescPtr attribute, const std::string& newName ) const = 0;

		std::string GlueAttributeNames(const TableAttributeDescList & attributes, const std::string & glue=std::string(",")) const;
		virtual std::string GlueAttributeNames(const TableAttributeValList & attributes, const std::string & glue=std::string(",")) const;
		static std::string GlueIds(const std::vector<int> & ids, const std::string & glue=std::string(","));
		std::string RequestFormat2DMLString( const IGeometry::RequestFormat & geometryformat ) const;
		virtual std::string formatDateTimeStamp(const std::string & colName) const;
		void RemoveMemberColumns( TableAttributeDescListPtr attributes ) const;

		virtual MoMaPropertyDescPtr CreateMoMaPropertyDesc(const std::string& name, TableAttributeDesc::DType dtype, Owner::OwnerId owner) const = 0;
		virtual MoMaPropertyDescPtr GetMoMaPropertyDesc(MoMaPropertyDesc::PROPERTYID propertyid) const;
		virtual MoMaPropertyDescListPtr ListMoMaPropertyDesc() const;
		virtual void RenameMoMaPropertyDesc(const MoMaPropertyDesc::PROPERTYID propertyid, const std::string& newname) const;
		virtual void DeleteMoMaPropertyDesc(const MoMaPropertyDesc::PROPERTYID propertyid) const;
		virtual void ChownMoMaPropertyDesc(const MoMaPropertyDesc::PROPERTYID propertyid, const long& newownerid) const;

		virtual MoMaPropertyValuePtr CreateMoMaPropertyValue(LinkedElement& element, const MoMaPropertyDesc& desc, MoMaPropertyValue::PVALUE value) const;
		virtual void SetMoMaPropertyValue(MoMaPropertyValue& value, MoMaPropertyValue::PVALUE newvalue) const;
		virtual void DeleteMoMaPropertyValue(const MoMaPropertyValue& value) const;
		virtual MoMaPropertyValueListPtr GetMoMaPropertyValuesForNode(const LinkedElement& element) const = 0;

		virtual MoMaPropertyValueListPtr ListMoMaPropertyValues(const LinkedElement& element) const;
		virtual MoMaPropertyValueListPtr ListMoMaPropertyValues(const MoMaPropertyDesc::PROPERTYID propertyid) const;

		/**
		 * Checks if an SRS with pair codeType:codeValue exists in the database.
		 *
		 * @return true if codeType:codeValue exists (false otherwise)
		 *
		 * @params validSrsId If this parameter is not -1 it will be checked, if
		 * the SRS with the given codeType:codeValue pair is stored with the id
		 * validSrsId. (Useful when updating an SRS and changing the
		 * codeType:codeValue).
		 */
		bool IsSRSCodeExisting(const std::string & codeType, const std::string & codeValue, long validSrsId = -1) const;
		void CheckCreateLinkAdjacencyInput(LinkAdjacency::LinkId parent, LinkAdjacency::ReferId refId, LinkAdjacency::TargetType refTarget, Owner::OwnerId owner) const;
		void CheckDropLinkAdjacencyPreconditions(LinkAdjacency::LinkId linkId) const;
		void CheckIfNodeStillLinkedTo(LinkAdjacency::ReferId refId, LinkAdjacency::TargetType targetType) const;
		void CheckIfColorValuesStillExistForColorScale(ColorScale::ColorScaleId csId) const;
		void CheckIfLinkHasNoValueInSameColorScale( ColorValue::ColorValueId cvId, LinkAdjacency::LinkId lId ) const;
		void CheckIfFeatureClassHasLinkedFeatures(const std::string &fullFeatureClassTableName) const;
		void CheckIfElementNameIsUnique(const std::string &name) const;
		void CheckIfFeatureNameIsUnique(const std::string &tableName, const std::string &featureName) const;
		void CheckIfDynamicColorScaleNameIsUnique(const std::string & themeName) const;
		std::string GetUniqueFeatureName(const std::string &tableName, const std::string &initialName) const;
		ColorScaleIdListPtr GetColorScalesToElement(Element::ElementId) const;
		void GetElementChildren(LinkAdjacency::LinkId parentId, const LinkAdjacencyListPtr &linkedNodes) const;
    public:
		LinkedElementPtr GetLinkedElement(LinkAdjacency::LinkId nodelink_id) const;
    protected:
		void GetFeatureChildren(LinkAdjacency::LinkId parentId, const LinkAdjacencyListPtr &linkedNodes) const;
		void GetElementParent( LinkAdjacency::LinkId childId, const LinkAdjacencyListPtr &linkedNodes ) const;
		void GetFeatureLinkIdGeometryIdPairs(FeatureLinkIdGeometryIdPairList &result, const std::string &geoIdString) const;
		long GetElementLevelIdByDepth(Level::LevelDepth depth) const;
		std::string GetGeoColumnNameFromGeoTableName(const std::string &fullFeatureClassName) const;
	
		virtual TableAttributeDescListPtr GetPrimaryKey(const std::string & tablename) const = 0;
		virtual void constructVariousPropertyNameAndValueList( bool updateSyntax, Geometry::StreamableGeometry::KeyValueListPtr variousProperties, TableAttributeDescListPtr attributes, std::string &variousPropertiesNames, std::string &variousPropertiesValues, const std::string & ignore, const std::string & warn_methodname, const bool executeimmediatesyntax = false) const = 0;
		void RemoveSerialPropertiesFromVariousPropertyList(Geometry::StreamableGeometry::KeyValueListPtr variousProperties);
		bool validAccessLevelId(long accessLevelId) const;
		void throwOnEmpty(const std::string &parameterValue, const std::string &parameterName, const std::string &methodName = "throwOnEmpty") const;
		//@}

		///@name Slices/Sections helper
		//@{
		virtual boost::shared_ptr<IntersectionResult> GetCrossSectionResult(
				const SectionImageParameters &params,
				const std::string &outputImageParameter) const;
		virtual boost::shared_ptr<IntersectionResult> GetHorizontalSectionResult(
				const MapImageParameters &params,
				const std::string &outputImageParameter) const;
		virtual boost::shared_ptr<IntersectionResult> GetVirtualboreholeResult(
				const BoreHoleImageParameters &params,
				const std::string &outputImageParameter) const;

		virtual void GetVirtualBoreholeShape(
				std::vector<unsigned char> &data,
				const BoreHoleImageParameters &params,
				const std::string &outputImageParameter) const;

		virtual void GetCrossSectionShape(
				std::vector<unsigned char> &data,
				const SectionImageParameters &params,
				const std::string &outputImageParameter) const;

		virtual void GetHorizontalSectionShape(
				std::vector<unsigned char> &data,
				const MapImageParameters &params,
				const std::string &outputImageParameter) const;
		virtual ColorMap::Id InsertColorMap(  const std::string & name, const Geometry::IGeometry::Color & nodataColor, const std::string &regex, long accessLevelId ) = 0;
		//@}

		PropertyAliasPtr GetPropertyAlias(long catalogId, const std::string &aliasTable, const std::string &propertyName) const;
		void CreateUpdatePropertyAlias(long catalogId, const std::string &aliasTable, const std::string &propertyName, const std::string &alias, long accessLevelId) const;
		void DropPropertyAlias(long catalogId, const std::string &aliasTable, const std::string &propertyName) const;
		PropertyAliasMapPtr GetPropertyAliasList(long catalogId, const std::string &aliasTable) const;
		std::string GetPropertyName(const ObjectPropertyDesc &op) const;
		std::string GetPropertyName(const SimplexPropertyDesc &sp) const;
		

		virtual std::string getEndpointTargetIdentifer() const;

		RDBConfigPtr getConfig() const;
	private:
		Geometry::GSTSRSRefPtr GetLastInsertedSRS();
		std::string featureListFromMomaKey(const GST::ClientUtils::MoMaKey &momakey) const;
	};

	//global class depend typedefs
	typedef boost::shared_ptr<AbstractRDBAccess> AbstractRDBAccessPtr;

} //of ns ClientUtils

		//Header file dependend exceptions
	namespace exceptions
	{
		class BadSPParameterType
			: public GSTRuntimeException
		{
		public:
			ClientUtils::SPParameter::DType badtype;

			BadSPParameterType(const std::string & throwLocation, const std::string & msg, const ClientUtils::SPParameter::DType& type)
				: GSTRuntimeException(throwLocation,msg)
				, badtype(type)
			{
			}
			virtual ~BadSPParameterType() throw()
			{
			}
		};
	}
} //of ns GST

#endif //_ABSTRACT_RDB_ACCESS_H_
